iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0

前言

不論是產各式報表,都與 Excel 脫離不了關係,產 Excel 屬於必備技能之一,以下示範如何產 Excel 檔

實作

這邊以 axlsx Gem 做範例,也有其他 Gem 也能做到,像是 xlsxtream 等,可參考此 pr

直接用 axlsx 最新版本直接 bundle 的話,會踩到雷,詳情,自己裝看看就知道了 XD

# Gemfile

gem 'rubyzip', '~> 2.3', '>= 2.3.2'
gem 'axlsx_rails', '~> 0.6.1'
gem 'axlsx', git: "https://github.com/randym/axlsx.git",
             ref: "c8ac844572b25fda358cc01d2104720c4c42f450"

將產 Excel 寫在 services,方便之後共用

# app/services/shops_excel/generator.rb

module ShopsExcel
  class Generator
    TITLES = %w[商家名稱 信箱 備註].freeze
    ROW_TYPES = %i[string string string].freeze

    def execute
      shops = Shop.all
      xlsx = Axlsx::Package.new
      workbook = xlsx.workbook
      workbook.add_worksheet(name: '商家清單') do |sheet|
        sheet.add_row(TITLES)
        shops.find_each do |shop|
          sheet.add_row(shop_row_data(shop), types: ROW_TYPES)
        end
      end
      xlsx
    end

    private

    def shop_row_data(shop)
      [
        shop.name,
        shop.email,
        shop.note
      ]
    end
  end
end
# config/routes.rb

get :export_shops_xlsx



---



# app/controllers/shops_controller.rb

def export_shops_xlsx
  # 實務上,並不建議直接在 controller 直接產 Excel,若資料很多的話,使用者體驗會不好 (會等很久)
  xlsx = ShopsExcel::Generator.new.execute

  send_data(xlsx.to_stream.read, type: 'application/xlsx', filename: '商家總表.xlsx')
end

若只是單純產一次就不會再產的話,可以在 rails console 直接下 code,如下

# rails console

xlsx = ShopsExcel::Generator.new.execute
xlsx.use_shared_strings = true
xlsx_file = Rails.root.join("data/test.xlsx")
xlsx.serialize(xlsx_file)

從網頁下載

產的 Excel 內容

小結

產 Excel 其實不難,難的是產的資料內容過於複雜且多時,可能會關聯超多 Model 、多個工作表 (worksheet),還要考量是否會 Memory Bloat

實務上並不建議直接在 controller 直接產 Excel ,資料太多的話,使用者體驗會不好,會等很久,通常會放 sidekiq 處理,完成後,再寄信給使用者

參考資料

  1. Axlsx GitHub

鐵人賽文章連結:https://ithelp.ithome.com.tw/articles/10272151
medium 文章連結:https://link.medium.com/GmNaDhwgQjb
本文同步發布於 小菜的 Blog https://riverye.com/

備註:之後文章修改更新,以個人部落格為主


上一篇
Day15 - 匯出(下載) PDF
下一篇
Day17 - 匯出 excel-測試篇
系列文
Ruby on Rails 與它們相關的東西 II30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言